﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Aliphant.Interfaces;

namespace Aliphant.IoC
{
    public class DiContainer : IDiContainer
    {
        // 存储所有服务的注册信息
        private readonly Dictionary<Type, ServiceRegistration> _registrations = new();
        private readonly Dictionary<string, ServiceRegistration> registrations = new();

        public void AddSingleton<TService, TImplementation>() where TImplementation : TService
        {
            Register<TService, TImplementation>(ServiceLifetime.Singleton);
        }

        public void AddSingleton<TService, TImplementation>(string name) where TImplementation : TService
        {
            Register<TImplementation>(name, ServiceLifetime.Singleton);
        }

        public void AddSingleton<TService>(TService instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException($"Service instance cannot be null");
            }
            _registrations[typeof(TService)] = new ServiceRegistration(
                typeof(TService),
                ServiceLifetime.Singleton,
                _ => instance
                );
        }

        public void AddSingleton<TService>(string name, TService instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException($"Service instance cannot be null");
            }
            registrations[name] = new ServiceRegistration(
                typeof(TService),
                ServiceLifetime.Singleton,
                _ => instance
                );
        }

        public void AddScoped<TService, TImplementation>() where TImplementation : TService
        {
            Register<TService, TImplementation>(ServiceLifetime.Scoped);
        }

        public void AddScoped<TService, TImplementation>(string name) where TImplementation : TService
        {
            Register<TImplementation>(name, ServiceLifetime.Scoped);
        }

        public void AddModule<TModule>() where TModule : IModule, new()
        {
            var module = new TModule();
            module.Register(this);
        }


        public T Resolve<T>()
        {
            return (T)Resolve(typeof(T));
        }

        public T Resolve<T>(string name)
        {
            return (T)Resolve(name);
        }


        /// <summary>
        /// 统一注册逻辑
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="lifetime"></param>
        private void Register<TService, TImplementation>(ServiceLifetime lifetime)
        {
            _registrations[typeof(TService)] = new ServiceRegistration(
                typeof(TImplementation),
                lifetime,
                CreateFactory(typeof(TImplementation))
                );
        }

        private void Register<TImplementation>(string name, ServiceLifetime lifetime)
        {
            registrations[name] = new ServiceRegistration(
                typeof(TImplementation),
                lifetime,
                CreateFactory(typeof(TImplementation))
                );
        }

        /// <summary>
        /// 统一解析逻辑
        /// </summary>
        /// <param name="serviceType"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        private object Resolve(Type serviceType)
        {
            if (!_registrations.TryGetValue(serviceType, out var registration))
                throw new InvalidOperationException($"Service {serviceType.Name} not registered.");

            // 单例：返回现有实例或创建新实例
            if (registration.Lifetime == ServiceLifetime.Singleton)
                return registration.Instance ??= registration.Factory(this);

            // 瞬态：每次创建新实例
            return registration.Factory(this);
        }

        private object Resolve(string name)
        {
            if(!registrations.TryGetValue(name, out var registration))
                throw new InvalidOperationException($"Service {name} not registered.");

            // 单例：返回现有实例或创建新实例
            if (registration.Lifetime == ServiceLifetime.Singleton)
                return registration.Instance ??= registration.Factory(this);

            // 瞬态：每次创建新实例
            return registration.Factory(this);
        }

        /// <summary>
        /// 创建实例的工厂方法（处理构造函数依赖）
        /// </summary>
        /// <param name="implementationType"></param>
        /// <returns></returns>
        private Func<DiContainer, object> CreateFactory(Type implementationType)
        {
            // 获取参数最长的构造函数
            var constructor = implementationType
                .GetConstructors()
                .OrderByDescending(c => c.GetParameters().Length)
                .First();

            return container =>
            {
                var parameters = constructor.GetParameters()
                    .Select(p => container.Resolve(p.ParameterType))
                    .ToArray();

                return constructor.Invoke(parameters);
            };
        }


        #region 内部类

        /// <summary>
        /// 服务注册信息
        /// </summary>
        private class ServiceRegistration
        {
            /// <summary>
            /// 实现类型
            /// </summary>
            public Type ImplementationType { get; }

            /// <summary>
            /// 生命周期
            /// </summary>
            public ServiceLifetime Lifetime { get; }

            /// <summary>
            /// 创建实例的工厂方法
            /// </summary>
            public Func<DiContainer, object> Factory { get; }

            /// <summary>
            /// 单例
            /// </summary>
            public object? Instance { get; set; }

            public ServiceRegistration(Type implementationType, ServiceLifetime lifetime, Func<DiContainer, object> factory)
            {
                ImplementationType = implementationType;
                Lifetime = lifetime;
                Factory = factory;
            }
        }

        /// <summary>
        /// 服务生命周期
        /// </summary>
        private enum ServiceLifetime
        {
            /// <summary>
            /// 全局单例
            /// </summary>
            Singleton,

            /// <summary>
            /// 区域
            /// </summary>
            Scoped
        }

        private bool disposedValue;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                }

                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
                // TODO: 将大型字段设置为 null
                foreach (var service in registrations.Keys)
                {
                    var ins = registrations[service];
                    ins = null;
                    //registrations[service] = null;
                }
                foreach (var service in _registrations.Keys)
                {
                    var ins = _registrations[service];
                    ins = null;
                    //_registrations[service] = null;
                }

                registrations.Clear();
                _registrations.Clear();
                disposedValue = true;
            }
        }

        // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        // ~DiContainer()
        // {
        //     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
        //     Dispose(disposing: false);
        // }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }



        #endregion
    }


}
